home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / tuner / tuner_io.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  8KB  |  348 lines

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <sys/time.h>
  5. #include <netinet/in.h>
  6. #include <netdb.h>
  7. #include <sys/stat.h>
  8.  
  9. #ifndef INADDR_NONE
  10. #define INADDR_NONE -1
  11. #endif
  12.  
  13. #include "tuner.h"
  14.  
  15. static do_stationcall();
  16.  
  17. char *dft_nets[] = { DFT_NETS, 0 };
  18.  
  19. char radio_host[64];        /* Host where radio runs */
  20.  
  21. int transmitter_port = CTLPRT_XMIT;    /* Default control port for transmitters */
  22. int radio_port = CTLPRT_RADIO;        /* Default control port for radios */
  23. struct sockaddr_in radio_addr;    /* Address of our radio */
  24. struct sockaddr_in bcast_addrs[MAXNET];    /* Addresses of transmitters */
  25. int num_bcast_addrs = 0;
  26.  
  27. struct station_info {
  28.     char name[MAXNAME];        /* station name */
  29.     int port;            /* UDP broadcast port */
  30.     int is_playing;        /* 1 if currently transmitting */
  31.     char logfile[MAXNAME];    /* Name of cdlog file */
  32.     int since;            /* Play time in minutes of current CD */
  33.     char cdname[MAXNAME];    /* Current CD name */
  34. };
  35.  
  36. struct station_info stations[MAXSTATION];
  37.  
  38. char *station_names[MAXSTATION];    /* Hack. Points into stations array */
  39. int num_stations;
  40.  
  41. char cur_name[MAXNAME];
  42. char cur_play[MAXNAME];
  43. char cur_time[MAXNAME];
  44. int cur_mute;
  45. int cur_port;
  46. int origtune = -1;
  47.  
  48. int sock;            /* Our socket */
  49. int sc_sock;            /* Stationcall socket */
  50.  
  51. char plbuf[MAXPLBUF][MAXNAME];
  52. char *playlist[MAXPLBUF];
  53. int num_playlist;
  54.  
  55. init_io() {
  56.     struct hostent *hent;
  57.     int i;
  58.  
  59.     for( i=0; i<MAXSTATION; i++)
  60.       station_names[i] = stations[i].name;
  61.     /*XXX Process args */
  62.     sock = opensock();
  63.     sc_sock = openscsock();
  64.  
  65.     /*
  66.     ** Divine address struct for radio station we're controlling.
  67.     */
  68.     if ( radio_host[0] == 0 ) {
  69.     if ( gethostname(radio_host, sizeof(radio_host)) < 0 ) {
  70.         perror("gethostname");
  71.         exit(1);
  72.     }
  73.     }
  74.     if ( (hent=gethostbyname(radio_host)) == 0 ) {
  75. #ifndef sun
  76.     herror(radio_host);
  77. #else
  78.     fprintf(stderr, "%s: Unknown host name\n", radio_host);
  79. #endif
  80.     exit(1);
  81.     }
  82.     radio_addr.sin_family = AF_INET;
  83.     radio_addr.sin_port = htons(radio_port);
  84.     memcpy(&radio_addr.sin_addr, hent->h_addr, hent->h_length);
  85.     /*
  86.     ** Create list of broadcast addresses for locating stations.
  87.     */
  88.     if ( num_bcast_addrs == 0 ) {
  89.     /*
  90.     ** No addresses in arguments. Do the defaults.
  91.     */
  92.     char **p;
  93.  
  94.     for( p=dft_nets; *p; p++ )
  95.       add_bcast_addr(*p);
  96.     }
  97.     /*
  98.     ** Obtain station info and current station.
  99.     */
  100.     get_stations();
  101.     get_curinfo();
  102.     origstation = cur_tune;
  103.     show_tuner(station_names, num_stations);
  104.     show_tune(cur_tune, cur_name, cur_play, cur_time, cur_mute);
  105.     show_playlist(playlist, num_playlist,1);
  106.     watch_socket(sc_sock, do_stationcall);
  107. }
  108.  
  109. get_stations() {
  110.     int i;
  111.     char *s;
  112.     struct station_info *p;
  113.  
  114.     /*
  115.     ** Clear old stations.
  116.     */
  117.     num_stations = 0;
  118.     /*
  119.     ** Broadcast info request.
  120.     */
  121.     for(i=0; i<num_bcast_addrs; i++)
  122.       sendsock(sock, &bcast_addrs[i], "radio:s");
  123.     /*
  124.     ** Receive replies.
  125.     */
  126.     while ( (s=recvsock(sock)) ) {
  127.     p = stations + num_stations;
  128.     if ( parse_stationcall(p, s) )
  129.       num_stations++;
  130.     }
  131. }
  132.  
  133. static
  134. do_stationcall(d1, d2, d3)
  135.     int d1, d2, d3;
  136. {
  137.     char *s;
  138.     struct station_info sistr;
  139.     int i;
  140.  
  141.     if ( (s=recvsock(sc_sock)) == NULL ) {
  142.     fprintf(stderr, "tuner: stationcall event without data?\n");
  143.     return;
  144.     }
  145.     if ( !parse_stationcall(&sistr, s) )
  146.       return;
  147.     for ( i=0; i<num_stations; i++)
  148.       if ( stations[i].port == sistr.port ) {
  149.       stations[i] = sistr;
  150.       if ( sistr.port == cur_port ) {
  151.           if( get_curinfo() )
  152.         show_playlist(playlist, num_playlist,1);
  153.           show_tune(cur_tune, cur_name, cur_play, cur_time, cur_mute);
  154.       }
  155.       return;
  156.       }
  157.     stations[num_stations] = sistr;
  158.     num_stations++;
  159.     show_tuner(station_names, num_stations);
  160. }
  161.     
  162. parse_stationcall(p, s)
  163.     struct station_info *p;
  164.     char *s;
  165. {
  166.     int port;
  167.     char name[MAXNAME], logname[MAXNAME], cdname[MAXNAME];
  168.     int is_playing, since;
  169.     int i;
  170.  
  171.     is_playing = 1;
  172.     since = -1;
  173.     cdname[0] = '\0';
  174.     logname[0] = '\0';
  175.     i = sscanf(s, "radio:S:%[^:]:%d:%d:%[^:]:%d:%[^\n]", name, &port,
  176.            &is_playing, logname, &since, cdname);
  177.     if ( i >= 2 ) {
  178.     strncpy(p->name, name, MAXNAME);
  179.     p->port = port;
  180.     p->is_playing = is_playing;
  181.     strncpy(p->logfile, logname, MAXNAME);
  182.     p->since = since;
  183.     strncpy(p->cdname, cdname, MAXNAME);
  184.     return 1;
  185.     }
  186.     fprintf(stderr, "Ill-formatted station call(%d): '%s'\n",i,  s);
  187.     return 0;
  188. }
  189.  
  190. add_bcast_addr(addr)
  191.     char *addr;
  192. {
  193.     struct sockaddr_in *sp;
  194.     unsigned long iaddr;
  195.  
  196.     sp = &bcast_addrs[num_bcast_addrs++];
  197.     if ( (iaddr=inet_addr(addr)) == INADDR_NONE) {
  198.     fprintf(stderr, "Ill-formatted address %s\n", addr);
  199.     exit(1);
  200.     }
  201.     
  202.     sp->sin_family = AF_INET;
  203.     sp->sin_addr.s_addr = iaddr;
  204.     sp->sin_port = htons(transmitter_port);
  205. }
  206.  
  207. get_curinfo() {
  208.     char *s;
  209.     int n;
  210.     int port, muteoff;
  211.     int i;
  212.     FILE *fp;
  213.     char buf[128];
  214.     int t;
  215.  
  216.     sendsock(sock, &radio_addr, "radio:i");
  217.     num_playlist = 0;
  218.     if ( s = recvsock(sock) ) {
  219.     /*
  220.     ** Parsing is funny, because older radio programs didn't have the
  221.     ** mute feature (so only send a single number, the port).
  222.     */
  223.     n = sscanf(s, "radio:I:%d:%d", &muteoff, &port);
  224.     if ( n == 0 ) {
  225.         fprintf(stderr, "Funny reply from radio program: %s\n", s);
  226.         return 1;
  227.     }
  228.     if ( n == 1 ) {
  229.         port = muteoff;
  230.         muteoff = 1;
  231.     }
  232.     cur_mute = !muteoff;
  233.     cur_port = port;
  234.     /*
  235.     ** Try to find the corresponding station
  236.     */
  237.     for(i=0; i<num_stations; i++) {
  238.         if ( cur_port == stations[i].port ) {
  239.         cur_tune = i+1;
  240.         strcpy(cur_name, stations[i].name);
  241.         strcpy(cur_play, stations[i].cdname);
  242.         t = stations[i].since / 60;
  243.         if ( t == 0 )
  244.           cur_time[0] = '\0';
  245.         else if ( t < 60 )
  246.           sprintf(cur_time, "%d minutes", t);
  247.         else
  248.           sprintf(cur_time, "%d hours", t/60);
  249.         if ( !stations[i].is_playing )
  250.           strcat(cur_time, "(Silent)");
  251.         if ( stations[i].logfile[0] )
  252.           return get_playlist(stations[i].logfile);
  253.         return 1;
  254.         }
  255.     }
  256.     if ( i == num_stations ) {
  257.         /* Couldn't find the station number */
  258.         cur_tune = 0;
  259.         sprintf(cur_name, "Unknown (port %d)", cur_port);
  260.         strcpy(cur_play, "?");
  261.         strcpy(cur_time, "?");
  262.         return 1;
  263.     }
  264.     }
  265.     fprintf(stderr, "Warning: radio program not responding\n");
  266.     strcpy(cur_name, "?");
  267.     strcpy(cur_time, "?");
  268.     strcpy(cur_play, "?");
  269.     cur_tune = 0;
  270.     return 1;
  271. }
  272.  
  273. void
  274. do_tune(station)
  275.     int station;
  276. {
  277.     char buf[32];
  278.  
  279.     if ( station == 0 ) return;
  280.     sprintf(buf, "radio:t:%d", stations[station-1].port);
  281.     sendsock(sock, &radio_addr, buf);
  282.     get_curinfo();
  283.     show_tune(cur_tune, cur_name, cur_play, cur_time, cur_mute);
  284.     show_playlist(playlist, num_playlist,1);
  285. }
  286.  
  287. /*
  288. ** do_mute - Mute radio
  289. */
  290. void
  291. do_mute(onoff)
  292.     int onoff;
  293. {
  294.     sendsock(sock, &radio_addr, onoff?"radio:0":"radio:1");
  295. }
  296.  
  297. /*
  298. ** get last MAXPLBUF entries of playlist file.
  299. */
  300. get_playlist(file)
  301.     char *file;
  302. {
  303.     FILE *fp;
  304.     int i, j;
  305.     static char fnbuf[MAXNAME];
  306.     struct stat sb;
  307.     static int mtime, saved_num_playlist;
  308.  
  309.     if ( strncmp(file, fnbuf, MAXNAME) == 0 ) {
  310.     if ( stat(file, &sb) >= 0 && sb.st_mtime == mtime ) {
  311.         /* Yes, cached copy still ok */
  312.         num_playlist = saved_num_playlist;
  313.         return 0;
  314.     }
  315.     }
  316.  
  317.     if ( (fp=fopen(file, "r")) == 0 )
  318.       return;
  319.  
  320.     strncpy(fnbuf, file, MAXNAME);
  321.     stat(file, &sb);
  322.     mtime = sb.st_mtime;
  323.  
  324.     i = 0;
  325.     while( (fgets(plbuf[i%MAXPLBUF], MAXNAME, fp)) ) i++;
  326.     if ( i == 0 ) {
  327.     num_playlist = 0;
  328.     saved_num_playlist = 0;
  329.     return;
  330.     }
  331.     i--;
  332.  
  333.     if ( i < MAXPLBUF ) {
  334.     num_playlist = i+1;
  335.     while ( i >= 0 ) {
  336.         playlist[i] = plbuf[i];
  337.         i--;
  338.     }
  339.     }
  340.     else {
  341.     for ( j=0; j<MAXPLBUF; j++) playlist[j] = plbuf[(i+j+1) % MAXPLBUF];
  342.     num_playlist = MAXPLBUF;
  343.     }
  344.     saved_num_playlist = num_playlist;
  345.     fclose(fp);
  346.     return 1;
  347. }
  348.